package org.eredlab.g4.rif.report.fcf;

import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.eredlab.g4.ccl.datastructure.Dto;
import org.eredlab.g4.rif.web.BaseAction;

/**
 * FlashReport数据包装类
 * 
 * @author XiongChun
 * @since 2010-10-13
 * @see BaseAction
 */
/*
 * 其实就是一个工具类而已，用于将所有传递过来的对象信息，用xml文档文件
 * 的形式来表达！那么所有信息的定义是在action中完成的，这个类只负责装换
 * 数据格式而已，共flash去解读！
 */
public class FcfDataMapper {
	private static Log log = LogFactory.getLog(FcfDataMapper.class);
	
	/**
	 * 简单图数据包装
	 * @param pList 数据集合
	 * @param configDto 配置对象
	 * @return String
	 */
	/*
	 * 正如上面所说，这是一个解析单个项目下的产品信息的xml文件转换，因此不能同
	 * 其他项目进行对比，第一参数是一个集合，装载的是指定项目下的所有产品信息实体
	 * 
	 */
    public static final String toFcfXmlData(List pList, GraphConfig pGraphConfig)
    {
    	//由于要将数据全部转换成xml文档格式，因此要创建一个文档对象！
		Document document = DocumentHelper.createDocument();
		//设置文档的字符编码！
		document.setXMLEncoding("GB2312");
		//给当前文档添加根元素！
		Element elRoot = document.addElement("graph");
		//将键值对用迭代器迭代，迭代一次就是一个Entry
		Iterator configIterator = pGraphConfig.entrySet().iterator();
		//迭代键值对！设置整体属性！
		while (configIterator.hasNext()) 
		{
			//得到当前的键值对实体！其实Entry是map类型里面的一个类型，可以看成一个实体，实体只包含键和值俩属性！
			Dto.Entry entry = (Dto.Entry)configIterator.next();
			//给根节点添加一个属性，属性名就是键的名，属性值就是键的值！这些是图标配置对象的全局属性，因此要在根节点上添加！
			elRoot.addAttribute((String)entry.getKey(), String.valueOf(entry.getValue()));
		}
		//便利单个图像实体信息！
		for(int i = 0; i < pList.size(); i++)
		{
			//每便利一个实体就创建一个set节点
			Element elRow = elRoot.addElement("set");
			//得到图像实体对象！
			Set set = (Set)pList.get(i);
			//得到实体的迭代器！
			Iterator it = set.entrySet().iterator();
			while(it.hasNext())
			{
				//解析实体的信息，并将其值作为set节点的属性！
				Dto.Entry entry = (Dto.Entry)it.next();
				elRow.addAttribute((String)entry.getKey(), String.valueOf(entry.getValue()));
			}
		}
		//将文档转换成XML文件！将所有的回车符转换成空字符串！即元素一次相互挨着！
		String outXml = document.asXML().replaceAll("\n", "");
		System.out.println("生成的XML文件是："+outXml);
		//将所有的双引号用单引号替代！
		return outXml.replace('"', '\'');
    }
    
    /**
     * 将简单图数据对象压入request
	 * @param pList 数据集合
	 * @param configDto 配置对象
     * @param request
     
    public static final void setReportData2Request(List pList, GraphConfig pGraphConfig, HttpServletRequest request){
    	
    }
    */
    
    /**
     * 组合图数据包装
     * @param pList
     * @param configDto
     * @param pCategoriesConfig
     * @return
     */
    
    /*
     * 如果直接看比较复杂我们可以先把他的结果xml编写出来，然后会发现他的解析规律
     * 例如：
     * 
     * 	
     * 
     * <?xml version="1.0" encoding="GB2312"?>
		<graph baseFontSize="12" baseFont="宋体" caption="Google软件2010年月度销售业绩图表" numberPrefix="$" canvasBorderThickness="0">
		
		注意集合直接输出的样子就是如下面所示！
		<categories font="宋体" categories="[{name=一月}, {name=二月}, {name=三月}, {name=四月}, {name=五月}, {name=六月}]" fontSize="12">
		
		<category name="一月"/>
		<category name="二月"/>
		<category name="三月"/>
		<category name="四月"/>
		<category name="五月"/>
		<category name="六月"/>
		
		</categories>
		
		<dataset dataList="[{value=22}, {value=44}, {value=12}]" seriesname="产品A" color="FDC12E">
		
		<set value="22"/>
		<set value="44"/>
		<set value="12"/>
		
		</dataset>
		
		<dataset dataList="[]" seriesname="产品B" color="56B9F9"/>
		
		</graph>
		分析：通过结果我们可以发现首先解析的分类信息，因为有多个类别，因此会有一个父节点，然后后面跟的都是子节点
		              子节点包含的信息就是分类的名称！同时在创建类别父节点时会将其所有对象属性转换成标签属性！对象有多少
		              属性跟节点就有多少属性！
     */
    public static final String toFcfXmlData(List pList, GraphConfig pGraphConfig, CategoriesConfig pCategoriesConfig)
    {
    	//得到一个文档对象-------------------------------------------------------------------------------------------文档定义部分
		Document document = DocumentHelper.createDocument();
		//设置文档的字符编码格式！
		document.setXMLEncoding("GB2312");
		
		
		//创建一个跟节点！--------------------------------------------------------------------------------------------定义根节点
		Element elRoot = document.addElement("graph");
		//开始迭代总体图标配置信息！并将值作为根节点的属性！
		Iterator configIterator = pGraphConfig.entrySet().iterator();
		while (configIterator.hasNext()) 
		{
			Dto.Entry entry = (Dto.Entry)configIterator.next();
			elRoot.addAttribute((String)entry.getKey(), String.valueOf(entry.getValue()));
		}
		//在根节点下创建一个分类节点！----------------------------------------------------------------------------------定义类别节点及其子节点
		Element elcategories = elRoot.addElement("categories");
		//迭代分类配置信息！
		Iterator categoriesIterator = pCategoriesConfig.entrySet().iterator();
		while (categoriesIterator.hasNext()) 
		{
			//将分类对象的属性作为分类节点的属性！
			Dto.Entry entry = (Dto.Entry)categoriesIterator.next();
			elcategories.addAttribute((String)entry.getKey(), String.valueOf(entry.getValue()));
		}
		//便利分类配置对象中的类别名称！
		for (int k = 0; k < pCategoriesConfig.getCategories().size(); k++) 
		{
			//创建一个字类别元素！
			Element elcategorie = elcategories.addElement("category");
			//得到类别子对象！每个子对象又是一个set集合！
			Categorie categorie = (Categorie)pCategoriesConfig.getCategories().get(k);
			//便利类别子对象！
			Iterator categorieIterator = categorie.entrySet().iterator();
			while(categorieIterator.hasNext())
			{
				//将类别对象的属性作为字类别标签的属性！
				Dto.Entry entry = (Dto.Entry)categorieIterator.next();
				elcategorie.addAttribute((String)entry.getKey(), String.valueOf(entry.getValue()));
			}
		}
		//开始定义项目想产品信息---------------------------------------------------------------------------------------------数据信息节点
		for(int i = 0; i < pList.size(); i++)
		{
			Element elRow = elRoot.addElement("dataset");
			//这也是一个实体，只不过这个实体包含的是单个项目下的所有产品实体信息！因此这个实体代表项目，实体中的集合代表当前项目下的所有产品信息，非常类适外键关联查询！
			DataSet ds = (DataSet)pList.get(i);
			//遍历项目实体，为了得到项目实体中的属性以及所有产品信息！
			Iterator it = ds.entrySet().iterator();
			while(it.hasNext())
			{
				Dto.Entry entry = (Dto.Entry)it.next();
				elRow.addAttribute((String)entry.getKey(), String.valueOf(entry.getValue()));
			}
			//遍历项目中的产品信息！
			for (int j = 0; j < ds.getData().size(); j++) 
			{
				//一个项目一个父标签，里面装载的子标签set是定义产品信息的标签！
				Element elSet = elRow.addElement("set");
				//得到当前产品信息实体！将其属性作为set标签的属性！
				Set set = (Set)ds.getData().get(j);
				Iterator setIterator = set.entrySet().iterator();
				while(setIterator.hasNext())
				{
					Dto.Entry entry = (Dto.Entry)setIterator.next();
					elSet.addAttribute((String)entry.getKey(), String.valueOf(entry.getValue()));
				}
			}
		}
		//将所有的回车符转换成空字符串！
		String outXml = document.asXML().replaceAll("\n", "");
		System.out.println("组合图XML文档："+outXml);
		return outXml.replace('"', '\'');
    }
}
